package pl.dsp.dsp1.processing;

public class WaveletFactory {
	private Signal signal;

	static public double[] H4 = { 0.482962913, 0.836516304, 0.224143868,
			-0.129409523 };
	static public double[] G4 = { H4[3], -H4[2], H4[1], -H4[0] };

	static public double[] H6 = { 0.47046721, 1.14111692, 0.650365,
			-0.19093442, -0.12083221, 0.0498175 };
	static public double[] G6 = { H6[5], -H6[4], H6[3], -H6[2], H6[1], -H6[0] };

	static public double[] H8 = { 0.32580343, 1.01094572, 0.8922014,
			-0.03957503, -0.26450717, 0.0436163, 0.0465036, -0.01498699 };
	static public double[] G8 = { H8[7], -H8[6],H8[5], -H8[4], H8[3], -H8[2], H8[1], -H8[0] };

	public WaveletFactory(Signal signal) {
		this.signal = signal;
		int targetSize = (int) Math.pow(2,
				(int) (Math.log(signal.size()) / Math.log(2)));
		while (this.signal.size() > targetSize) {
			this.signal.remove(this.signal.size() - 1);
		}
	}

	public Signal getSimpleTransform(double[] f1, double[] f2) {
		Signal resultSignal = new Signal(signal.getT1(),
				signal.getSamplingPeriod());

		for (int row = 0; row < signal.size(); row++) {
			double[] filter = (row % 2 == 0) ? f1 : f2;
			SignalValue product = new SimpleValue(0);

			for (int i = 0; i < filter.length; i++) {
				int signalPos = ((row / 2) * 2 + i) % signal.size();
				product = product.add(signal.get(signalPos).multiply(
						new SimpleValue(filter[i])));
			}

			resultSignal.add(product);
		}

		return resultSignal;
	}

	public Signal getInverseTransform(double[] f1, double[] f2) {
		Signal resultSignal = new Signal(signal.getT1(),
				signal.getSamplingPeriod());

		for (int i = 0; i < signal.size(); i++) {
			resultSignal.add(new SimpleValue(0));
		}

		for (int column = 0; column < signal.size(); column++) {
			double[] filter = (column % 2 == 0) ? f1 : f2;

			for (int i = 0; i < filter.length; i++) {
				int signalPos = ((column / 2) * 2 + i) % signal.size();

				SignalValue newValue = resultSignal.get(signalPos).add(
						signal.get(column).multiply(
								new SimpleValue(filter[i])));
				resultSignal.set(signalPos, newValue);
			}
		}

		return resultSignal;
	}
}
